package com.tianxia120.website.data.config;

import com.jfinal.config.*;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.dialect.Sqlite3Dialect;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.plugin.hikaricp.HikariCpPlugin;
import com.jfinal.template.Engine;
import com.jfinal.template.source.ClassPathSourceFactory;
import com.tianxia120.website.admin.routes.AdminRoutes;
import com.tianxia120.website.admin.routes.LoginRoutes;
import com.tianxia120.website.bean.model._MappingKit;
import com.tianxia120.website.data.handler.AllowHeaderHandler;
import com.tianxia120.website.data.handler.CorsHandler;
import com.tianxia120.website.data.handler.OptionsHandler;
import com.tianxia120.website.data.handler.XssHandler;
import com.tianxia120.website.data.interceptors.ExceptionInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.event.EventPlugin;

/**
 * @createTime: 2018/2/8
 * @author: HingLo
 * @description: 配置文件
 */
@Slf4j
public class WebsiteConfig extends JFinalConfig {

    /**
     * 通过操作系统来判断是否是开发者模式
     */
    private boolean debug = System.getProperty("os.name").toLowerCase().startsWith("win");

    /**
     * 此方法用来配置JFinal常量值，如开发模式常量devMode的配置，如下代码配置了JFinal运行在开发模式：
     *
     * @param constants constants
     */
    @Override
    public void configConstant(Constants constants) {
        prop = PropKit.use("db.properties");
        //如果是 ，就是设置为开发者模式
        constants.setDevMode(debug);
        //文件上传保存目录，如果在是在开发者模式下就放在自定义的文件夹，服务器就放入临时文件夹中
        constants.setBaseUploadPath(debug ? "E:/root/temp/" : "/tmp/");
        //设置日期返回的格式
        constants.setJsonDatePattern("yyyy-MM-dd");
        // 启用注入
        constants.setInjectDependency(true);

        // 自定义返回Render ,之所以重写此方法,是因为重写了系统框架中的错误返回
        constants.setRenderFactory(new MyRenderFactory());
    }

    /**
     * 此方法用来配置访问路由，
     *
     * @param routes routes
     */
    @Override
    public void configRoute(Routes routes) {
        routes.add(new LoginRoutes());
        routes.add(new AdminRoutes());

    }

    /**
     * 此方法用来配置Template Engine，以下是代码示例：
     *
     * @param engine engine
     */

    @Override
    public void configEngine(Engine engine) {
        //共享数据引擎配置(模板对象配置) 由于对象被全局共享，所以需要注意线程安全问题，尽量只共享常量以及无状态对象。
        //eg: me.addShareObject("key",object);

    }

    /**
     * 插件配置
     *
     * @param plugins plugins
     */
    @Override
    public void configPlugin(Plugins plugins) {
        //配置数据库连接池
        HikariCpPlugin hikariCpPlugin = new HikariCpPlugin(prop.get("jdbcUrl"), "", "");
        hikariCpPlugin.setDriverClass("org.sqlite.JDBC");
        //将连接池的插件配置到插件中
        plugins.add(hikariCpPlugin);
        //创建连接池插件对象
        ActiveRecordPlugin activeRecordPlugin = new ActiveRecordPlugin(hikariCpPlugin);
        // 设置方言
        activeRecordPlugin.setDialect(new Sqlite3Dialect());
        //设置显示sql语句
        activeRecordPlugin.setShowSql(true);
        //sql动态管理插件
        activeRecordPlugin.getEngine().setSourceFactory(new ClassPathSourceFactory());
        activeRecordPlugin.addSqlTemplate("website.sql");
        //应用连接池插件
        plugins.add(activeRecordPlugin);
        //添加表与实体的对应关系
        _MappingKit.mapping(activeRecordPlugin);
        // 添加ehcache支持
        plugins.add(new EhCachePlugin());

        EventPlugin plugin = new EventPlugin();
        // 设置为异步，默认同步，或者使用`threadPool(ExecutorService executorService)`自定义线程池。
        plugin.async();
        // 设置扫描jar包，默认不扫描
        plugin.scanJar();
        plugins.add(plugin);

    }

    @Override
    public void configInterceptor(Interceptors interceptors) {
        //添加全局异常处理拦截器
        interceptors.add(new ExceptionInterceptor());
    }

    /**
     * 此方法用来配置JFinal的Handler，如下代码配置了名为ResourceHandler的处理器<br>
     * Handler可以接管所有web请求，并对应用拥有完全的控制权，可以很方便地实现更高层的功能性扩展。
     *
     * @param handlers handler
     */
    @Override
    public void configHandler(Handlers handlers) {

        // Ajax 跨域处理
        if (debug) {
            handlers.add(new CorsHandler());
        }
        // 过滤掉 options 请求操作
        handlers.add(new OptionsHandler());
        // 允许读取的Header
        handlers.add(new AllowHeaderHandler());
        //Xss攻击处理
        handlers.add(new XssHandler());
    }

    /**
     * 系统启动完成后回调
     */
    @Override
    public void afterJFinalStart() {

    }

    /***
     *  系统关闭之前回调
     */
    @Override
    public void beforeJFinalStop() {
        log.info("系统准备关闭");
    }
}
